package dao;

import static util.Constantes.OPPORTUNITY;
import static util.Constantes.STRENGTH;
import static util.Constantes.THREAT;
import static util.Constantes.WEAKNESS;

import java.util.ArrayList;
import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.criterion.Restrictions;

import util.HibernateUtil;
import vo.SwotElementVO;
import vo.SwotVO;
import entity.BSC_Perspective;
import entity.Opportunity;
import entity.SWOT;
import entity.SWOTElement;
import entity.StrategicPerspective;
import entity.StrategicPlan;
import entity.Strength;
import entity.Threat;
import entity.Weakness;

public class SwotDAO {
	
	private List<SwotElementVO> getSwotElements(List<SWOTElement> elements, String elementType){
		List<SwotElementVO> listaRetorno = new ArrayList<SwotElementVO>();
		
		for(SWOTElement se:elements){
			SwotElementVO vo = new SwotElementVO();
			vo.setName(se.getName());
			vo.setRelevancia(Integer.toString(se.getRelevance()));
			vo.setId(se.getId());
			vo.setElementType(elementType);
			
			String perspectives = "";
			for(BSC_Perspective bscp:se.getPerspectives()){
				if (perspectives.equalsIgnoreCase("")){
					perspectives = bscp.getStrategicPerspective().getAcronym();
				}
				else{
					perspectives += ", " + bscp.getStrategicPerspective().getAcronym();
				}
			}
			vo.setPerspective(perspectives);
			
			listaRetorno.add(vo);
		}
		
		return listaRetorno;
	}
	
	private List<SwotElementVO> getListStrength(SWOT swot) {
		List<SWOTElement> lista = new ArrayList<SWOTElement>();
		for(SWOTElement se:swot.getListStrength()){
			lista.add(se);
		}
		
		return getSwotElements(lista, STRENGTH);
	}

	private List<SwotElementVO> getListWeakness(SWOT swot) {
		List<SWOTElement> lista = new ArrayList<SWOTElement>();
		for(SWOTElement se: swot.getListWeakness()){
			lista.add(se);
		}		
		
		return getSwotElements(lista, WEAKNESS);
	}

	private List<SwotElementVO> getListOpportunity(SWOT swot) {
		List<SWOTElement> lista = new ArrayList<SWOTElement>();
		for(SWOTElement se: swot.getListOpportunity()){
			lista.add(se);
		}		
		
		return getSwotElements(lista, OPPORTUNITY);
	}

	private List<SwotElementVO> getListThreat(SWOT swot) {
		List<SWOTElement> lista = new ArrayList<SWOTElement>();
		for(SWOTElement se: swot.getListThreat()){
			lista.add(se);
		}		
		
		return getSwotElements(lista, THREAT);
	}
	
	public SwotVO getSwot(int strategicPlanId) {
		Session sessao = HibernateUtil.getSession();
		SwotVO vo = getSwot(strategicPlanId, sessao);
		sessao.close();
		return vo;
	}

	public SwotVO getSwot(int strategicPlanId, Session sessao) {
		StrategicPlan strategicPlan = (StrategicPlan) sessao.load(StrategicPlan.class, strategicPlanId);
		
		SwotVO swotVO = new SwotVO();
		SWOT swot = strategicPlan.getSwot();
		if (swot != null){
			swotVO.setId(swot.getId());
			swotVO.setNome(swot.getName());
			swotVO.setDescricao(swot.getDescription());
			swotVO.setListStrength(getListStrength(swot));
			swotVO.setListWeakness(getListWeakness(swot));
			swotVO.setListOpportunity(getListOpportunity(swot));
			swotVO.setListThreat(getListThreat(swot));
		}
		
		return swotVO;
	}
	
	public void saveSwot(SwotVO vo, List<Integer> listaStrengthRemovido, List<Integer> listaWeaknessRemovido, List<Integer> listaOpportunityRemovido, 
			List<Integer> listaThreatRemovido) {
		SWOT swot;
		
		Session sessao = HibernateUtil.getSession();
		
		if (vo.getId() == 0){
			swot = new SWOT();
		}
		else{
			swot = getSWOTById(vo.getId(), sessao);
		}
		
		StrategicPlan sp = (StrategicPlan) sessao.load(StrategicPlan.class, vo.getStrategicPlanId());
		
		swot.setName(vo.getNome());
		swot.setDescription(vo.getDescricao());
		
		if (vo.getListStrength() != null){
			for(SwotElementVO svo: vo.getListStrength()){
				Strength s;
				
				if (svo.getId() > 0){
					s = (Strength) sessao.load(Strength.class, svo.getId());
					swot.getListStrength().remove(s);
				}
				else{
					s = new Strength();
					s.setPerspectives(new ArrayList<BSC_Perspective>());
				}
				
				s.setName(svo.getName());
				s.setRelevance(Integer.parseInt(svo.getRelevancia()));
				s.setSwot(swot);
				s.setPerspectives(new ArrayList<BSC_Perspective>());
				
				for(String acronym:svo.getListPerspectives()){
					Criteria criterios = sessao.createCriteria(StrategicPerspective.class);
					criterios.add(Restrictions.eq("acronym", acronym));
					criterios.add(Restrictions.eq("organization.id", sp.getOrganizacao().getId()));
					StrategicPerspective spp = (StrategicPerspective) criterios.list().get(0);						
					
					criterios = sessao.createCriteria(BSC_Perspective.class);
					criterios.add(Restrictions.eq("strategicPerspective.id", spp.getId()));
					criterios.add(Restrictions.eq("strategicPlan.id", vo.getStrategicPlanId()));					
					BSC_Perspective bscp = (BSC_Perspective) criterios.list().get(0);
					
					s.getPerspectives().add(bscp);
				}
				
				if (swot.getListStrength() == null){
					swot.setListStrength(new ArrayList<Strength>());
				}
				
				swot.getListStrength().add(s);
			}
		}
		
		if (listaStrengthRemovido != null){
			for(int id: listaStrengthRemovido){
				Strength s = (Strength) sessao.load(Strength.class, id);
				swot.getListStrength().remove(s);				
			}
		}
		
		if (vo.getListWeakness() != null){
			for(SwotElementVO svo: vo.getListWeakness()){
				Weakness w;
				
				if (svo.getId() > 0){
					w = (Weakness) sessao.load(Weakness.class, svo.getId());
					swot.getListWeakness().remove(w);
				}
				else{
					w = new Weakness();
					w.setPerspectives(new ArrayList<BSC_Perspective>());
				}
				
				w.setName(svo.getName());
				w.setRelevance(Integer.parseInt(svo.getRelevancia()));
				w.setSwot(swot);
				w.setPerspectives(new ArrayList<BSC_Perspective>());
				
				for(String acronym:svo.getListPerspectives()){
					Criteria criterios = sessao.createCriteria(StrategicPerspective.class);
					criterios.add(Restrictions.eq("acronym", acronym));
					criterios.add(Restrictions.eq("organization.id", sp.getOrganizacao().getId()));
					StrategicPerspective spp = (StrategicPerspective) criterios.list().get(0);						
					
					criterios = sessao.createCriteria(BSC_Perspective.class);
					criterios.add(Restrictions.eq("strategicPerspective.id", spp.getId()));
					criterios.add(Restrictions.eq("strategicPlan.id", vo.getStrategicPlanId()));					
					BSC_Perspective bscp = (BSC_Perspective) criterios.list().get(0);
					
					w.getPerspectives().add(bscp);
				}
				
				if (swot.getListWeakness() == null){
					swot.setListWeakness(new ArrayList<Weakness>());
				}
				
				swot.getListWeakness().add(w);
			}
		}
		
		if (listaWeaknessRemovido != null){
			for(int id: listaWeaknessRemovido){
				Weakness w = (Weakness) sessao.load(Weakness.class, id);
				swot.getListWeakness().remove(w);				
			}
		}
		
		if (vo.getListOpportunity() != null){
			for(SwotElementVO svo: vo.getListOpportunity()){
				Opportunity o;
				
				if (svo.getId() > 0){
					o = (Opportunity) sessao.load(Opportunity.class, svo.getId());
					swot.getListOpportunity().remove(o);
				}
				else{
					o = new Opportunity();
					o.setPerspectives(new ArrayList<BSC_Perspective>());
				}
				
				o.setName(svo.getName());
				o.setRelevance(Integer.parseInt(svo.getRelevancia()));
				o.setSwot(swot);
				o.setPerspectives(new ArrayList<BSC_Perspective>());
				
				for(String acronym:svo.getListPerspectives()){
					Criteria criterios = sessao.createCriteria(StrategicPerspective.class);
					criterios.add(Restrictions.eq("acronym", acronym));
					criterios.add(Restrictions.eq("organization.id", sp.getOrganizacao().getId()));
					StrategicPerspective spp = (StrategicPerspective) criterios.list().get(0);						
					
					criterios = sessao.createCriteria(BSC_Perspective.class);
					criterios.add(Restrictions.eq("strategicPerspective.id", spp.getId()));
					criterios.add(Restrictions.eq("strategicPlan.id", vo.getStrategicPlanId()));					
					BSC_Perspective bscp = (BSC_Perspective) criterios.list().get(0);
					
					o.getPerspectives().add(bscp);
				}
				
				if (swot.getListOpportunity() == null){
					swot.setListOpportunity(new ArrayList<Opportunity>());
				}
				
				swot.getListOpportunity().add(o);
			}
		}
		
		if (listaOpportunityRemovido != null){
			for(int id:listaOpportunityRemovido){
				Opportunity o = (Opportunity) sessao.load(Opportunity.class, id);
				swot.getListOpportunity().remove(o);
			}
		}
		
		if (vo.getListThreat() != null){
			for(SwotElementVO svo: vo.getListThreat()){
				Threat t;
				
				if (svo.getId() > 0){
					t = (Threat) sessao.load(Threat.class, svo.getId());
					swot.getListOpportunity().remove(t);
				}
				else{
					t = new Threat();
					t.setPerspectives(new ArrayList<BSC_Perspective>());
				}
				
				t.setName(svo.getName());
				t.setRelevance(Integer.parseInt(svo.getRelevancia()));
				t.setSwot(swot);
				t.setPerspectives(new ArrayList<BSC_Perspective>());
				
				for(String acronym:svo.getListPerspectives()){
					Criteria criterios = sessao.createCriteria(StrategicPerspective.class);
					criterios.add(Restrictions.eq("acronym", acronym));
					criterios.add(Restrictions.eq("organization.id", sp.getOrganizacao().getId()));
					StrategicPerspective spp = (StrategicPerspective) criterios.list().get(0);						
					
					criterios = sessao.createCriteria(BSC_Perspective.class);
					criterios.add(Restrictions.eq("strategicPerspective.id", spp.getId()));
					criterios.add(Restrictions.eq("strategicPlan.id", vo.getStrategicPlanId()));					
					BSC_Perspective bscp = (BSC_Perspective) criterios.list().get(0);
					
					t.getPerspectives().add(bscp);
				}
				
				if (swot.getListThreat() == null){
					swot.setListThreat(new ArrayList<Threat>());
				}
				
				swot.getListThreat().add(t);
			}
		}
		
		if (listaThreatRemovido != null){
			for(int id:listaThreatRemovido){
				Threat t = (Threat) sessao.load(Threat.class, id);
				swot.getListThreat().remove(t);
			}
		}
		
		sp.setSwot(swot);
		swot.setStrategicPlan(sp);
		
		Transaction tx = sessao.beginTransaction();
		try{			
			sessao.saveOrUpdate(swot);
			tx.commit();
			sessao.clear();
		}
		catch(Exception e){
			e.printStackTrace();
			tx.rollback();
			sessao.flush();
		}
	}
	
	private SWOT getSWOTById(int id, Session sessao){		
		SWOT swot = (SWOT) sessao.load(SWOT.class, id);
		return swot;
	}
}
